package xj.graph2d.shapes;

import static xj.graph2d.DrawShapeConstants.d;
import static xj.util.xml.XMLUtil.getXMLAttributeString;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.apache.commons.codec.binary.Base64;

import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeBase;
import xj.graph2d.DrawShapeFactory;
import xj.graph2d.RectangleShape;
import xj.lang.CodeWriter;
import xj.util.xml.XMLUtil;

public class IconShape extends RectangleShape implements ShapeConstants {

  public IconShape() {
  }

  public IconShape(Icon icon) {
    this(icon, null, false);
  }

  public IconShape(Icon icon, String iconName) {
    this(icon, iconName, false);
  }

  public IconShape(Icon icon, boolean createComp) {
    this(icon, null, createComp);
  }

  public IconShape(Icon icon, String iconName, boolean createComp) {
    super(false, createComp);
    setIcon(icon, iconName);
  }

  @Override
  public DrawShape makeInstance() {
    return new IconShape(null, comp != null);
  }

  @Override
  public void copyTo(DrawShapeBase s) 
    throws CloneNotSupportedException {
    super.copyTo(s);
    if (s instanceof IconShape) {
      IconShape is = (IconShape) s;
      is.icon = icon;
      is.iconName = iconName;
      is.iconHeight = iconHeight;
      is.iconWidth = iconWidth;
    }
  }

  @Override
  public String getName() {
    return "Icon";
  }

  public String getIconName() {
    return iconName;
  }

  public Icon getIcon() {
    return icon;
  }

  public void setIcon(Icon icon) {
    setIcon(icon, null);
  }

  public void setIcon(Icon icon, String iconName) {
    this.icon = icon;
    this.iconName = iconName;
    if (icon != null) {
      iconWidth = icon.getIconWidth();
      iconHeight = icon.getIconHeight();
      float x1 = (float) p1.getX();
      float y1 = (float) p1.getY();
      setEnds(x1, y1, x1 + iconWidth, y1 + iconHeight);
    }
  }

  @Override
  public void draw(Graphics2D g2) {
    float x = (float) Math.min(p1.getX(), p2.getX());
    float y = (float) Math.min(p1.getY(), p2.getY());
    float w = (float) Math.abs(p1.getX() - p2.getX());
    float h = (float) Math.abs(p1.getY() - p2.getY());
    if (icon != null && (int) w >= 1 && (int) h >= 1) {
      icon.paintIcon(null, g2, (int) x, (int) y);
    }

    if (showborder) {
      g2.draw(new Rectangle2D.Float(x, y, w, h));
    }
  }

  @Override
  public void calculateBounds() {
    // super.calculateBounds();
    // int w = (int) Math.abs(p1.getX() - p2.getX());
    // int h = (int) Math.abs(p1.getY() - p2.getY());
    float x = (float) Math.min(p1.getX(), p2.getX());
    float y = (float) Math.min(p1.getY(), p2.getY());
    float w = (float) Math.abs(p1.getX() - p2.getX());
    float h = (float) Math.abs(p1.getY() - p2.getY());
    bounds.setRect(x, y, w, h);
    framebounds.setRect(x - d, y - d, w + 2 * d, h + 2 * d);
  }

  @Override
  public void adjustBounds() {
  }

  @Override
  protected void writeXMLElements(CodeWriter out, int mode,
      String namespacePrefix) {
    if (out != null) {
      super.writeXMLElements(out, mode, namespacePrefix);

      String rname = getPrefixedName("Icon", namespacePrefix);
      if (iconName != null) {
	out.println("<" + rname + ' ' + getXMLAttributeString("name", iconName)  + "/>");
      } else {
	out.print("<" + rname + ">");
	try {
	  ByteArrayOutputStream bout = new ByteArrayOutputStream(iconHeight * iconWidth);
	  BufferedImage bimg = new BufferedImage(iconWidth, iconHeight, BufferedImage.TYPE_INT_RGB);
	  Graphics2D g = bimg.createGraphics();
	  icon.paintIcon(null, g, 0, 0);
	  ImageIO.write(bimg, "png", bout);
	  byte[] ba = Base64.encodeBase64(bout.toByteArray());
	  String str = new String(ba, "US-ASCII");
	  out.print(str);
	} catch (IOException e) {
	  System.err.println(e.getMessage());
	}
	out.println("</" + rname + ">");
      }
    }
  }

  @Override
  protected void processXMLElement(org.w3c.dom.Element e, String namespaceURI) {
    if (e != null) {
      String nodename = e.getLocalName();
      if ("Icon".equals(nodename)) {
	String iname = e.getAttribute("name");
	if (iname != null) {
	  DrawShapeFactory factory = DrawShapeFactory.getInstance();
	  Icon icon = factory.getIcon(iname);
	  setIcon(icon, iname);
	} else {
	  try {
	    String val = XMLUtil.getTextChildNodeValue(e);
	    if (val != null) {
	      val = val.trim();
	    }
	    byte[] ba = val.getBytes("US-ASCII");
	    byte[] ba2 = Base64.decodeBase64(ba);
	    ByteArrayInputStream bin = new ByteArrayInputStream(ba2);
	    BufferedImage bimg = ImageIO.read(bin);
	    setIcon(new ImageIcon(bimg));
	  } catch (IOException ex) {
	    System.err.println(ex.getMessage());
	  }
	}
      } else {
	super.processXMLElement(e, namespaceURI);
      }
    }
  }

  /*
         * public void writeXML(CodeWriter out, int mode, String
         * namespacePrefix) { if (out != null) { String nodename =
         * getPrefixedName("IconShape", namespacePrefix); out.indentInc();
         * out.println("<" + nodename + " shaded=\"" + shaded + "\"
         * showBorder=\"" + showborder + "\">"); writeXMLBase(out, mode,
         * namespacePrefix);
         * 
         * String rname = getPrefixedName("Icon", namespacePrefix); if (iconName !=
         * null) { out.println("<" + rname + " name=\"" + iconName + "\"/>"); }
         * else { out.print("<" + rname + ">"); try { ByteArrayOutputStream
         * bout = new ByteArrayOutputStream(iconHeight * iconWidth);
         * BufferedImage bimg = new BufferedImage(iconWidth, iconHeight,
         * BufferedImage.TYPE_INT_RGB); Graphics2D g = bimg.createGraphics();
         * icon.paintIcon(null, g, 0, 0); ImageIO.write(bimg, "png", bout);
         * byte[] ba = Base64.encodeBase64(bout.toByteArray()); String str = new
         * String(ba, "US-ASCII"); out.print(str); } catch (IOException e) {
         * System.err.println(e.getMessage()); } out.println("</" + rname +
         * ">"); }
         * 
         * out.thisIndentDec(); out.println("</" + nodename + ">"); } }
         * 
         * public void setAttrFromXML(org.w3c.dom.Element node, String
         * namespaceURI) { if (node != null) { String uri =
         * node.getNamespaceURI(); if (namespaceURI == null ||
         * namespaceURI.equals(uri)) { NodeList nodes = node.getChildNodes(); if
         * (nodes != null) { int n = nodes.getLength(); for (int i = 0; i < n;
         * i++) { Node cnode = nodes.item(i); if (cnode.getNodeType() ==
         * org.w3c.dom.Node.ELEMENT_NODE && "Icon".equals(cnode.getLocalName())) {
         * Element e = (Element) cnode; String iname = e.getAttribute("name");
         * if (iname != null) { DrawShapeFactory factory =
         * DrawShapeFactory.getInstance(); Icon icon = factory.getIcon(iname);
         * setIcon(icon, iname); } else { try { String val =
         * XMLUtil.getTextChildNodeValue(e); if (val != null) { val =
         * val.trim(); } byte[] ba = val.getBytes("US-ASCII"); byte[] ba2 =
         * Base64.decodeBase64(ba); ByteArrayInputStream bin = new
         * ByteArrayInputStream(ba2); BufferedImage bimg = ImageIO.read(bin);
         * setIcon(new ImageIcon(bimg)); } catch (IOException ex) {
         * System.err.println(ex.getMessage()); } } } } }
         * 
         * super.setAttrFromXML(node, namespaceURI); calculateBounds(); } } }
         */

  @Override
  public boolean isZeroSize() {
    return super.isZeroSize() || (icon == null);
  }

  protected Icon icon;

  protected String iconName;

  protected int iconHeight, iconWidth;

}
